﻿using System;
using System.Collections.Generic;
//
using CookComputing.XmlRpc;
using PerceptiveMCAPI.Types;
//
namespace PerceptiveMCAPI.Methods
{
   public class campaignUpdate : Api_BaseExecute
   {
      private new campaignUpdateInput Input { get; set; }
      private campaignUpdateOutput Output { get; set; }
      // =============================================== constructors
      public campaignUpdate() { }
      // ---------
      public campaignUpdate( campaignUpdateInput input ) { Input = input; }
      // =============================================== Execute
      public campaignUpdateOutput Execute()
      {
         // empty constructor & Execute() is bad
         if ( Input == null )
            throw new ArgumentException( "Input class not provided" );
         // do the deed
         Output = Execute( Input );
         return Output;
      }
      // ---------------------------------------------
      public campaignUpdateOutput Execute( campaignUpdateInput input )
      {
         Input = input;
         Output = new campaignUpdateOutput( Input );
         ValidationIsOK = true;
         //-------------------------
         if ( Input.api_Validate )
         {
            Output.api_ValidatorMessages = ValidateInput.Validate( Input );
            ValidationIsOK = ValidateInput.IsOK( Output.api_ValidatorMessages );
         }
         //------------------------- do it
         if ( ValidationIsOK )
         {
            ApiRun( Input, input.parms.apikey );  // execute API & format output
         }
         // ---
         return Output;
      }

      #region ================================================================= API Calls

      // ---------------------------------------------------------- XmlRpc
      protected override void ExecuteXmlRpc()
      {
         try
         {
            // ---------------------------------- rpc format & call -------------------------------------------
            bool rpcResult;
            string type = Input.parms.value.GetType().Name;
            if ( type.Contains( "Dictionary" ) ) type = "Dictionary";
            switch ( type )
            {
               case "String":
                  string sVal = Input.parms.value.ToString();
                  rpcResult = apiXmlRpc.api.campaignUpdate( Input.parms.apikey, Input.parms.cid, Input.parms.name, sVal );
                  break;
               case "Int32":
                  int iVal = Convert.ToInt32( Input.parms.value );
                  rpcResult = apiXmlRpc.api.campaignUpdate( Input.parms.apikey, Input.parms.cid, Input.parms.name, iVal );
                  break;
               case "Boolean":
                  bool bVal = Convert.ToBoolean( Input.parms.value );
                  rpcResult = apiXmlRpc.api.campaignUpdate( Input.parms.apikey, Input.parms.cid, Input.parms.name, bVal );
                  break;
               case "campaignTracking":
                  campaignTracking tracking = (campaignTracking)Input.parms.value;
                  rpcResult = apiXmlRpc.api.campaignUpdate( Input.parms.apikey, Input.parms.cid, Input.parms.name, tracking );
                  break;
               case "campaignSegmentOptions":
                  XmlRpcStruct segment_opts =
                     apiXmlRpc.FormatSegmentOptions( (campaignSegmentOptions)Input.parms.value );
                  rpcResult = apiXmlRpc.api.campaignUpdate( Input.parms.apikey, Input.parms.cid, Input.parms.name, segment_opts );
                  break;
               case "Dictionary":      // analytics, type_opts, content
                  XmlRpcStruct typOpts = apiXmlRpc.FormatDictionaryToXmlRpcStruct( (Dictionary<string, string>)Input.parms.value );
                  rpcResult = apiXmlRpc.api.campaignUpdate( Input.parms.apikey, Input.parms.cid, Input.parms.name, typOpts );
                  break;
               default:
                  throw new ArgumentException( string.Format( "Value type: '{0}', not supported", type ) );
            }
            Output.Format( rpcResult );
         }
         catch ( XmlRpcFaultException fex )
         {
            Output.api_ErrorMessages.Add( apiException.FormatError( fex ) );
         }
         catch ( Exception ex )
         {
            Output.api_ErrorMessages.Add( apiException.FormatError( ex ) );
         }
      }

      // ---------------------------------------------------------- Serial Post
      protected override void ExecuteSerialPost()
      {
         try
         {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            dict.Add( "apikey", Input.parms.apikey );
            dict.Add( "cid", Input.parms.cid );

            // convert object
            string type = Input.parms.value.GetType().Name;
            if ( type.Contains( "Dictionary" ) ) type = "Dictionary";
            switch ( type )
            {
               case "String":
               case "Int32":
                  dict.Add( "name", Input.parms.name );
                  dict.Add( "value", Input.parms.value.ToString() );
                  break;
               case "Boolean":
                  // 2010-Apr-17 : auto_tweet doesn't recognize 'False' so switched to 0/1 values
                  dict.Add( "name", Input.parms.name );
                  string b = ( bool.Parse( Input.parms.value.ToString() ) ) == true ? "1" : "0";
                  dict.Add( "value", b );
                  break;
               case "campaignTracking":
                  campaignTracking tracking = (campaignTracking)Input.parms.value;
                  dict.Add( "name", "tracking" );
                  dict.Add( "value[opens]", tracking.opens.ToString() );
                  dict.Add( "value[html_clicks]", tracking.html_clicks.ToString() );
                  dict.Add( "value[text_clicks]", tracking.text_clicks.ToString() );
                  break;
               case "campaignSegmentOptions":
                  dict.Add( "name", "segment_opts" );
                  campaignSegmentOptions so = (campaignSegmentOptions)Input.parms.value;
                  if ( so.conditions.Count > 0 )
                  {
                     dict.Add( "value[match]", so.match );
                     int i = -1;
                     foreach ( campaignSegmentCondition cond in so.conditions )
                     {
                        i++;
                        dict.Add( string.Format( "value[conditions][{0}][field]", i ), cond.field ?? "" );
                        dict.Add( string.Format( "value[conditions][{0}][op]", i ), cond.op ?? "" );
                        dict.Add( string.Format( "value[conditions][{0}][value]", i ), cond.value ?? "" );
                        if ( !string.IsNullOrEmpty( cond.extra ) )
                           dict.Add( string.Format( "value[conditions][{0}][extra]", i ), cond.extra );
                     }
                  }
                  else
                  { dict.Add( "value", "" ); }
                  break;
               case "Dictionary":
                  dict.Add( "name", Input.parms.name );
                  Dictionary<string, string> values = (Dictionary<string, string>)Input.parms.value;
                  foreach ( KeyValuePair<string, string> kv in values )
                  {
                     dict.Add( string.Format( "value[{0}]", kv.Key ), kv.Value ?? "" );
                  }
                  break;
               default:
                  throw new ArgumentException( string.Format( "Value type: '{0}', not supported for Serial requests", type ) );
            }
            // -- do it
            string api_Request = "";
            string api_Response = apiSerial.ProcessRequest( Input, dict, out api_Request );
            Output.Format( api_Request, api_Response );
         }
         catch ( Exception ex )
         {
            Output.api_ErrorMessages.Add( apiException.FormatError( ex ) );
         }
      }

      #endregion
   }
}
